﻿using System;
using System.Data;
using Oracle.DataAccess.Client;

using BizElements.Core.ProviderComponents;

namespace BizElements.Core.Oracle
{
    sealed class OracleCommandBuilder : IDbCommandBuilder
    {
        private static readonly IParameterRenderer parameterRenderer = new OracleParameterRenderer();

        public IDbCommand BuildCommand(string cmdText, DbParameterCollection parameters, CommandType cmdType)
        {
            IDbCommand cmd = new OracleCommand();
            cmd.CommandText = cmdText;
            cmd.CommandType = cmdType;
            if (Settings.DefaultCommandTimeout != null)
                cmd.CommandTimeout = Settings.DefaultCommandTimeout.Value;

            foreach (DbParameter par in parameters)
                cmd.Parameters.Add(ConvertToNativeParameter(par, cmdType));

            return cmd;
        }

        private static IDbDataParameter ConvertToNativeParameter(DbParameter dbParameter, CommandType cmdType)
        {
            IDbDataParameter clone = new OracleParameter() { IsNullable = dbParameter.IsNullable };

            // Remove leading ':' character for stored procedures.
            if (cmdType == CommandType.StoredProcedure)
            {
                string name = parameterRenderer.RenderParameterName(dbParameter);
                if (name.StartsWith(":", StringComparison.Ordinal))
                    name = name.Substring(1, name.Length - 1);

                clone.ParameterName = name;
            }
            else
            {
                clone.ParameterName = parameterRenderer.RenderParameterName(dbParameter);
            }

            if (dbParameter.PassMode == SpArgumentPassMode.DataTableFilledByAdapter)
                ((OracleParameter)clone).OracleDbType = OracleDbType.RefCursor; // = OracleType.Cursor;
            else if (dbParameter.DbType == DbType.Currency)
                clone.DbType = DbType.Decimal;
            else
                clone.DbType = dbParameter.DbType;

            clone.Direction = dbParameter.Direction;
            clone.Precision = dbParameter.Precision;
            clone.Scale = dbParameter.Scale;
            clone.Size = dbParameter.Size;
            clone.SourceColumn = dbParameter.SourceColumn;
            clone.SourceVersion = dbParameter.SourceVersion;
            clone.Value = dbParameter.Value;

            return clone;
        }
    }
}
